package com.example.redisson.redisson;

import jakarta.annotation.Resource;
import org.redisson.api.RLock;
import org.redisson.api.RReadWriteLock;
import org.redisson.api.RedissonClient;
import org.springframework.stereotype.Service;

@Service
public class ReadWriteLockService {

    @Resource
    private RedissonClient redissonClient;

    /**
     * Redisson 读写锁示例，分布式锁，参考 https://www.bookstack.cn/read/redisson-wiki-zh/8.-%E5%88%86%E5%B8%83%E5%BC%8F%E9%94%81%E5%92%8C%E5%90%8C%E6%AD%A5%E5%99%A8.md
     */
    public void readWriteLock() {
        // 获取一个读写锁对象，如果不存在则创建一个
        RReadWriteLock readWriteLock = redissonClient.getReadWriteLock("myReadWriteLock");

        // 获取读锁，多个线程可以同时获取读锁，但只能有一个线程获取写锁。
        RLock readLock = readWriteLock.readLock();

        // 获取写锁，写锁是独占的，一次只能有一个线程获取写锁。
        // 获取写锁会阻止其他线程获取读锁或写锁，直到写锁被释放
        RLock writeLock = readWriteLock.writeLock();

        // 读取操作
        try {
            readLock.lock();
            // 读取临界区内的代码
            System.out.println("已获取读锁！读取共享资源...");
            Thread.sleep(1000); // 模拟读取操作
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
            throw new RuntimeException(e);
        } finally {
            if (readLock.isHeldByCurrentThread()) {
                readLock.unlock();
            }
        }

        // 写入操作
        try {
            writeLock.lock();
            // 写入临界区内的代码
            System.out.println("已获取写锁！写入共享资源...");
            Thread.sleep(2000); // 模拟写入操作
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
            throw new RuntimeException(e);
        } finally {
            if (writeLock.isHeldByCurrentThread()) {
                writeLock.unlock();
            }
        }

    }

}
